<?php


namespace app\api\controller;


use app\common\controller\Api;

class Huada extends Api
{
    protected $noNeedLogin = ['*'];
    protected $noNeedRight = ['*'];

    //华大平台id
    private $appId;
    //华大平台secret
    private $appSecret;
    //请求主地址
    private $gateway;
    //测试环境
    private $devgateway;

    public function __construct()
    {
        $this->appId = C("payconfig.huada_appid");
        $this->appSecret = C("payconfig.huada_appSecret");
        $this->gateway = "https://iot.bhz.com.cn/httpapi/";
        $this->devgateway = "https://iottest.bzbcloud.cn/httpapi/";
    }

    //获取accessToken
    public function get_access_token(){
        $url = $this->gateway."accessToken";

        $token = M("token")->where('name','huada')->find();
        if(!empty($token) && !empty($token['access_token']) && $token['token_time']>(time()-7100)){
            return $token['access_token'];
        }
        //获取token
        $data['appId'] = $this->appId;
        $data['salt'] = self::nonce_str();
        $data['timestamp'] = time();
        log_result('huada',"获取token入参：".json_encode($data));
        $data['sign'] = $this->debugSignProcess($data);
        $res = $this->http_curl($url, 'post', $data);
        log_result('huada',"获取token结果：".$res);
        $res = json_decode($res,true);
        if($res['code']==0){
            //保存token
            M("token")->where('name','huada')->save([
               'access_token'=>$res['data']['accessToken'],
                'token_time'=>time(),
                'expires_in'=>$res['data']['expiresIn'],
            ]);
            return $res['data']['accessToken'];
        }
        return null;
    }

    /**
     * 发送设备指令
     * @param $deviceName 音箱名称
     * @param $amount 金额
     * @param $discountAmount 消费券金额
     * @param $voiceId 支付方式。取值：1：支付宝到账，2：微信到账，3：云闪付到账。
     * @param $voiceMsg 播报文本
     * @param string $deviceId  音箱ID
     * @return mixed
     */
    public function send_voice($deviceName,$amount,$discountAmount,$voiceId,$voiceMsg,$deviceId="1234"){
        $url = $this->gateway."devices/commands";

        $param['deviceId'] = $deviceId;
        $param['deviceName'] = $deviceName;
        $param['method'] = "thing.service.voice";
        $param['props'] = [
            'reqTimeStamp' => time(),
            'amount' => "".$amount,
            'discountAmount' => intval($discountAmount),
            'voiceMsg' => $voiceMsg,
            'voiceId' => intval($voiceId),
        ];
        $param['callType'] = 'sync';
        log_result('huada',"发送指令入参：".json_encode($param));
        $res = $this->http_curl($url,"post",$param);
        log_result('huada',"发送指令结果：".$res);
        return json_decode($res,true);
    }

    public function send_voice_test($deviceName){
        $url = $this->gateway."devices/commands";

        $param['deviceId'] = "1234";
        $param['deviceName'] = $deviceName;
        $param['method'] = "thing.service.voice";
        $param['props'] = [
            'reqTimeStamp' => time(),
            'amount' => "1688",
            'discountAmount' => intval(0),
            'voiceMsg' => "收到付款金额：16.88元",
            'voiceId' => 2,
        ];
        $param['callType'] = 'sync';
        log_result('huada',"发送指令入参：".json_encode($param));
        $res = $this->http_curl($url,"post",$param);
        log_result('huada',"发送指令结果：".$res);
        return json_decode($res,true);
    }

    /**
     * 准备签名参数
     * @param array $params
     * @return array
     */
    private function prepareParams($params) {
        $signParams = $params;

        // 移除sign字段（如果存在）
        unset($signParams['sign']);

        // 移除空值参数（根据API要求）
        foreach ($signParams as $key => $value) {
            if ($value === null || $value === null) {
                unset($signParams[$key]);
            }
        }

        return $signParams;
    }

    /**
     * 生成JSON字符串
     * @param array $params
     * @return string
     */
    private function generateJsonString($params) {
        // 关键：使用正确的JSON编码选项
        $jsonString = json_encode($params, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

        if ($jsonString === false) {
            throw new RuntimeException("JSON编码失败: " . json_last_error_msg());
        }

        // 移除所有空格和换行符
        $jsonString = preg_replace('/\s+/', '', $jsonString);

        return $jsonString;
    }

    /**
     * 生成密钥
     * @return string
     */
    private function generateKey() {
        //dump("appSecret:".$this->appSecret);
        $sha1Result = sha1($this->appSecret, true);
        //dump("appSecret SHA1:".$sha1Result);
        $key = substr($sha1Result, 0, 16);
        //dump("取16位生成key:".$key);
        if (strlen($key) !== 16) {
            throw new RuntimeException("密钥生成失败，长度应为16字节");
        }

        return $key;
    }

    /**
     * PKCS#5填充
     * @param string $data
     * @param int $blockSize
     * @return string
     */
    private function pkcs5Pad($data, $blockSize) {
        $padLength = $blockSize - (strlen($data) % $blockSize);
        return $data . str_repeat(chr($padLength), $padLength);
    }

    /**
     * AES加密
     * @param string $data
     * @param string $key
     * @return string
     */
    private function aesEncrypt($data, $key) {
        $encrypted = openssl_encrypt(
            $data,
            'AES-128-ECB',
            $key,
            OPENSSL_RAW_DATA
        );

        if ($encrypted === false) {
            throw new RuntimeException("AES加密失败: " . openssl_error_string());
        }

        return $encrypted;
    }

    /**
     * 验证参数
     * @param array $params
     */
    private function validateParams($params) {
        if (!is_array($params)) {
            throw new InvalidArgumentException("参数必须是数组");
        }

        if (empty($this->appSecret)) {
            throw new RuntimeException("appSecret不能为空");
        }

        // 检查必需参数
        $requiredParams = ['appId', 'timestamp', 'salt'];
        foreach ($requiredParams as $param) {
            if (!isset($params[$param]) || empty($params[$param])) {
                throw new InvalidArgumentException("缺少必需参数: " . $param);
            }
        }
    }
    /**
     * 调试签名生成过程
     * @param array $params
     */
    public function debugSignProcess($params) {
        try {
            //dump("=== 签名生成调试 ===");
            //dump("原始参数：".json_encode($params));
            $signParams = $this->prepareParams($params);
            //dump("处理后的参数：".json_encode($signParams));
            ksort($signParams);
            //dump("排序后的参数：".json_encode($signParams));
            $jsonString = $this->generateJsonString($signParams);
            //dump("JSON字符串：".$jsonString);
            $data = sha1($jsonString, true);
            //dump("SHA1摘要:".$data);
            //dump("SHA1摘要(HEX):：".bin2hex($data));
            //dump("SHA1长度：".strlen($data) . " 字节");
            $key = $this->generateKey();
            //dump("key(HEX):".bin2hex($key));
            $paddedData = $this->pkcs5Pad($data, 16);
            //dump("填充后数据：".$paddedData);
            //dump("填充后数据长度：".strlen($paddedData)." 字节");
            $encrypted = $this->aesEncrypt($data, $key);
            $sign = bin2hex($encrypted);

            //dump("最终签名：".$sign);
            //dump("签名长度：".strlen($sign)."字符");

            return $sign;

        } catch (Exception $e) {
            echo "调试过程出错: " . $e->getMessage() . "\n";
            return false;
        }
    }


    //随机32位字符串
    public static function nonce_str()
    {
        $result = '';
        $str = 'QWERTYUIOPASDFGHJKLZXVBNMqwertyuioplkjhgfdsamnbvcxz';
        for ($i = 0; $i < 32; $i++) {
            $result .= $str[rand(0, 48)];
        }
        return $result;
    }
    function http_curl($url = "", $type = 'get', $arr = '',$head = '')
    {
        if(strstr($url,"accessToken")){
            $headers = [
                'Content-Type: application/json',
                'X-Accept-Version: 1',
            ];
        }else{
            $headers = [
                'Content-Type: application/json',
                'X-Accept-Version: 1',
                'Authorization: Bearer '.$this->get_access_token(),
            ];
        }


        $ch = curl_init();
        //2.设置curl的参数
        curl_setopt($ch, CURLOPT_URL, $url); //设置我们的url
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //curl_exec执行成功则返回执行结果
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        if ($type == 'post') {
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($arr)); //将$arr发送给$url
        }
        //curl_setopt($ch,CURLINFO_CONTENT_TYPE,"application/json");
        curl_setopt($ch,CURLOPT_HTTPHEADER,$headers);
        $output = curl_exec($ch);
        curl_close($ch);
        return $output;
    }
}